package com.jourwon.spring.boot.service.impl;

import com.jourwon.spring.boot.model.vo.PluginInfoVO;
import com.jourwon.spring.boot.prop.Pf4jProperties;
import com.jourwon.spring.boot.service.PluginManagerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.pf4j.PluginState;
import org.pf4j.PluginWrapper;
import org.pf4j.spring.SpringPluginManager;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * 插件管理接口实现类
 *
 * @author JourWon
 * @date 2022/3/24
 */
@Slf4j
@Service
public class PluginManagerServiceImpl implements PluginManagerService {

    private static final String ZIP = ".zip";

    @Resource
    private Pf4jProperties pf4jProperties;

    @Resource
    private SpringPluginManager pluginManager;

    @Override
    public PluginInfoVO getPluginInfoVO(String pluginId) {
        PluginWrapper pluginWrapper = pluginManager.getPlugin(pluginId);
        return PluginInfoVO.toPluginInfoVO(pluginWrapper);
    }

    @Override
    public List<PluginInfoVO> listPluginInfoVO() {
        List<PluginWrapper> plugins = pluginManager.getPlugins();
        List<PluginInfoVO> list = new ArrayList<>();
        for (PluginWrapper pluginWrapper : plugins) {
            PluginInfoVO pluginInfoVO = PluginInfoVO.toPluginInfoVO(pluginWrapper);
            list.add(pluginInfoVO);
        }
        return list;
    }

    @Override
    public PluginInfoVO loadPlugin(String pluginPath) {
        String loadPluginId = pluginManager.loadPlugin(Paths.get(pluginPath));
        PluginWrapper pluginWrapper = pluginManager.getPlugin(loadPluginId);
        PluginInfoVO pluginInfoVO = PluginInfoVO.toPluginInfoVO(pluginWrapper);
        return pluginInfoVO;
    }

    @Override
    public PluginInfoVO uploadAndLoadPlugin(MultipartFile file) {
        if (file.isEmpty()) {
            throw new RuntimeException("上传的文件不能为空");
        }
        // 获取文件名
        String fileName = file.getOriginalFilename();
        log.info("上传的文件名为{}", fileName);
        // 获取文件的后缀名
        assert fileName != null;
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        if (!ZIP.equalsIgnoreCase(suffixName)) {
            throw new RuntimeException("文件后缀名必须是zip");
        }
        // 文件上传后的路径
        String filePath = pf4jProperties.getPluginsDir();
        String pluginPath = filePath + fileName;
        File dest = new File(pluginPath);
        if (dest.exists()) {
            throw new RuntimeException("请勿上传同名的插件");
        }

        try {
            // 复制插件文件
            file.transferTo(dest);

            // 加载插件
            PluginInfoVO pluginInfoVO = loadPlugin(pluginPath);

            return pluginInfoVO;
        } catch (Exception e) {
            log.error("上传插件异常:{}", e.getMessage(), e);
            // 异常情况删除上传插件,zip和解压后的文件夹
            FileUtils.deleteQuietly(dest);

            String dirPath = dest.getPath().replaceFirst(ZIP, "");
            FileUtils.deleteQuietly(new File(dirPath));
            throw new RuntimeException("上传插件异常");
        }
    }

    @Override
    public PluginState startPlugin(String pluginId) {
        return pluginManager.startPlugin(pluginId);
    }

    @Override
    public PluginState stopPlugin(String pluginId) {
        return pluginManager.stopPlugin(pluginId);
    }

    @Override
    public boolean deletePlugin(String pluginId) {
        return pluginManager.deletePlugin(pluginId);
    }

}
